package model

import (
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/validation"
	"mime/multipart"
	"nspel/entity"
	"nspel/util"
	"time"
)

type PostStudentsImport struct {
	ImportFile multipart.File
}

func (postStudentsImport *PostStudentsImport) Validate(c *beego.Controller) error {
	file, fileHeader, err := c.GetFile("import")
	if err != nil {
		return err
	}
	if !util.ValidateFileType(fileHeader, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") {
		return err
	}
	postStudentsImport.ImportFile = file
	return nil
}

type GetStudentsListAdmin struct {
	ProvinceId   int64
	CityId       int64
	AreaId       int64
	SchoolName   string
	JoinYear     int64
	SchoolRollId string
	PageSize     int64
	CurrentPage  int64
}

func (getStudentsListAdmin *GetStudentsListAdmin) Validate(provinceId string, cityId string, areaId string, schoolName string, joinYear string, schoolRollId string, pageSize string, currentPage string, c *beego.Controller) bool {
	var err error
	getStudentsListAdmin.ProvinceId, err = c.GetInt64(provinceId)
	if err != nil {
		return false
	}
	getStudentsListAdmin.CityId, err = c.GetInt64(cityId)
	if err != nil {
		return false
	}
	getStudentsListAdmin.AreaId, err = c.GetInt64(areaId)
	if err != nil {
		return false
	}
	getStudentsListAdmin.SchoolName = c.GetString(schoolName)
	getStudentsListAdmin.JoinYear, err = c.GetInt64(joinYear)
	if err != nil {
		return false
	}
	getStudentsListAdmin.SchoolRollId = c.GetString(schoolRollId)
	getStudentsListAdmin.PageSize, err = c.GetInt64(pageSize)
	if err != nil {
		return false
	}
	getStudentsListAdmin.CurrentPage, err = c.GetInt64(currentPage)
	if err != nil {
		return false
	}
	return true
}

type GetStudentsListArea struct {
	JoinYear     int64
	SchoolId     int64
	SchoolRollId string
	PageSize     int64
	CurrentPage  int64
}

func (getStudentsListArea *GetStudentsListArea) Validate(joinYear string, schoolId string, schoolRollId string, pageSize string, currentPage string, c *beego.Controller) bool {
	var err error
	getStudentsListArea.JoinYear, err = c.GetInt64(joinYear)
	if err != nil {
		return false
	}
	getStudentsListArea.SchoolId, err = c.GetInt64(schoolId)
	if err != nil {
		return false
	}
	getStudentsListArea.SchoolRollId = c.GetString(schoolRollId)
	getStudentsListArea.PageSize, err = c.GetInt64(pageSize)
	if err != nil {
		return false
	}
	getStudentsListArea.CurrentPage, err = c.GetInt64(currentPage)
	if err != nil {
		return false
	}
	return true
}

type GetStudentsListSchool struct {
	SchoolRollId string
	PageSize     int64
	CurrentPage  int64
}

func (getStudentsListSchool *GetStudentsListSchool) Validate(schoolRollId string, pageSize string, currentPage string, c *beego.Controller) bool {
	var err error
	getStudentsListSchool.SchoolRollId = c.GetString(schoolRollId)
	getStudentsListSchool.PageSize, err = c.GetInt64(pageSize)
	if err != nil {
		return false
	}
	getStudentsListSchool.CurrentPage, err = c.GetInt64(currentPage)
	if err != nil {
		return false
	}
	return true
}

type PostSchoolRollIdValidateExist struct {
	Id           int64  `json:"id"`
	SchoolRollId string `json:"schoolRollId"`
}

func (postSchoolRollIdValidateExist *PostSchoolRollIdValidateExist) Validate(uid int64, authority byte) (bool, error) {
	if postSchoolRollIdValidateExist.Id < 0 || len(postSchoolRollIdValidateExist.SchoolRollId) == 0 {
		return false, nil
	}
	if postSchoolRollIdValidateExist.Id > 0 {
		if authority == entity.ManagerAuthority.Area {
			area := new(entity.Area)
			err := area.SelectAllByUserId(uid)
			if err != nil {
				return false, err
			}
			student := new(entity.Student)
			err = student.SelectAllById(postSchoolRollIdValidateExist.Id)
			if err != nil {
				return false, err
			}
			if student.ExperimentAreaId != area.Id {
				return false, nil
			}
		} else if authority == entity.ManagerAuthority.School {
			school := new(entity.School)
			err := school.SelectAllByUserId(uid)
			if err != nil {
				return false, err
			}
			student := new(entity.Student)
			err = student.SelectAllById(postSchoolRollIdValidateExist.Id)
			if err != nil {
				return false, err
			}
			if student.SchoolId != school.Id {
				return false, nil
			}
		}
	}
	return true, nil
}

type PostStudentPhoneExist struct {
	Id    int64  `json:"id"`
	Phone string `json:"phone"`
}

func (postStudentPhoneExist *PostStudentPhoneExist) Validate(uid int64, authority byte) (bool, error) {
	if postStudentPhoneExist.Id < 0 || len(postStudentPhoneExist.Phone) == 0 {
		return false, nil
	}
	if postStudentPhoneExist.Id > 0 {
		if authority == entity.ManagerAuthority.Area {
			area := new(entity.Area)
			err := area.SelectAllByUserId(uid)
			if err != nil {
				return false, err
			}
			student := new(entity.Student)
			err = student.SelectAllById(postStudentPhoneExist.Id)
			if err != nil {
				return false, err
			}
			if student.ExperimentAreaId != area.Id {
				return false, nil
			}
		} else if authority == entity.ManagerAuthority.School {
			school := new(entity.School)
			err := school.SelectAllByUserId(uid)
			if err != nil {
				return false, err
			}
			student := new(entity.Student)
			err = student.SelectAllById(postStudentPhoneExist.Id)
			if err != nil {
				return false, err
			}
			if student.SchoolId != school.Id {
				return false, nil
			}
		}
	}
	return true, nil
}

type PostStudentModify struct {
	Id           int64     `json:"id"`
	SchoolRollId string    `json:"schoolRollId" valid:"MinSize(1);MaxSize(30)"`
	Name         string    `json:"name" valid:"MinSize(1);MaxSize(10)"`
	Sex          string    `json:"sex" valid:"Match(/^(男)|(女)$/)"`
	Nation       string    `json:"nation" valid:"Match(/^([1-9])|(1[1-9])|(2[1-9])|(3[1-9])|(4[1-9])|(5[1-6])|(9[7-8])$/)"`
	Birthday     time.Time `json:"birthday"`
	IdentityId   string    `json:"identityId" valid:"MaxSize(18)"`
	GradeYear    int64     `json:"gradeYear"`
	Grade        string    `json:"grade" valid:"Match(/^(1[1-6])|(2[1-3])|(3[1-3])$/)"`
	Class        string    `json:"class" valid:"Match(/^([1-9])|([1-9][1-9])$/)"`
	StudentId    string    `json:"studentId" valid:"MinSize(1);MaxSize(20)"`
	Phone        string    `json:"phone"`
	Address      string    `json:"address" valid:"MaxSize(255)"`
}

func (postStudentModify *PostStudentModify) Validate(uid int64, authority byte) (bool, error) {
	valid := validation.Validation{}
	b, err := valid.Valid(postStudentModify)
	if err != nil || !b {
		return b, err
	}
	if len(postStudentModify.Phone) > 0 {
		valid.Phone(postStudentModify.Phone, "phone")
		if valid.HasErrors() {
			return false, nil
		}
		student := new(entity.Student)
		err = student.SelectAllByPhone(postStudentModify.Phone)
		if err != nil && err != orm.ErrNoRows {
			return false, err
		} else if err == nil {
			if student.Id != postStudentModify.Id {
				return false, nil
			}
		}
	}
	if authority == entity.ManagerAuthority.Area {
		area := new(entity.Area)
		err := area.SelectAllByUserId(uid)
		if err != nil {
			return false, err
		}
		student := new(entity.Student)
		err = student.SelectAllById(postStudentModify.Id)
		if err != nil {
			return false, err
		}
		if student.ExperimentAreaId != area.Id {
			return false, nil
		}
	} else if authority == entity.ManagerAuthority.School {
		school := new(entity.School)
		err := school.SelectAllByUserId(uid)
		if err != nil {
			return false, err
		}
		student := new(entity.Student)
		err = student.SelectAllById(postStudentModify.Id)
		if err != nil {
			return false, err
		}
		if student.SchoolId != school.Id {
			return false, nil
		}
	}
	return true, nil
}

type PostStudentAdd struct {
	CountryId        int64     `json:"-"`
	ProvinceId       int64     `json:"provinceId"`
	CityId           int64     `json:"cityId"`
	AreaId           int64     `json:"-"`
	ExperimentAreaId int64     `json:"experimentAreaId"`
	SchoolId         int64     `json:"schoolId"`
	SchoolRollId     string    `json:"schoolRollId" valid:"MinSize(1);MaxSize(30)"`
	Name             string    `json:"name" valid:"MinSize(1);MaxSize(10)"`
	Sex              string    `json:"sex" valid:"Match(/^(男)|(女)$/)"`
	Nation           string    `json:"nation" valid:"Match(/^([1-9])|(1[1-9])|(2[1-9])|(3[1-9])|(4[1-9])|(5[1-6])|(9[7-8])$/)"`
	Birthday         time.Time `json:"birthday"`
	IdentityId       string    `json:"identityId" valid:"MaxSize(18)"`
	GradeYear        int64     `json:"gradeYear"`
	Grade            string    `json:"grade" valid:"Match(/^(1[1-6])|(2[1-3])|(3[1-3])$/)"`
	Class            string    `json:"class" valid:"Match(/^([1-9])|([1-9][1-9])$/)"`
	StudentId        string    `json:"studentId" valid:"MinSize(1);MaxSize(20)"`
	Phone            string    `json:"phone"`
	Address          string    `json:"address" valid:"MaxSize(255)"`
}

func (postStudentAdd *PostStudentAdd) Validate(uid int64, authority byte) (bool, error) {
	valid := validation.Validation{}
	b, err := valid.Valid(postStudentAdd)
	if err != nil || !b {
		return b, err
	}
	if len(postStudentAdd.Phone) > 0 {
		valid.Phone(postStudentAdd.Phone, "phone")
		if valid.HasErrors() {
			return false, nil
		}
		student := new(entity.Student)
		err = student.SelectAllByPhone(postStudentAdd.Phone)
		if err != nil && err != orm.ErrNoRows {
			return false, err
		} else if err == nil {
			return false, nil
		}
	}
	student := new(entity.Student)
	err = student.SelectAllBySchoolRollId(postStudentAdd.SchoolRollId)
	if err == nil {
		return false, nil
	} else if err != nil && err != orm.ErrNoRows {
		return false, err
	}
	school := new(entity.School)
	if authority == entity.ManagerAuthority.School {
		err = school.SelectAllByUserId(uid)
		if err != nil {
			return false, nil
		}
	} else if authority == entity.ManagerAuthority.Administrator || authority == entity.ManagerAuthority.Area {
		err = school.SelectAllById(postStudentAdd.SchoolId)
		if err != nil {
			return false, nil
		}
	}
	postStudentAdd.CountryId = school.CountryId
	postStudentAdd.ProvinceId = school.ProvinceId
	postStudentAdd.CityId = school.CityId
	postStudentAdd.AreaId = school.AreaId
	postStudentAdd.ExperimentAreaId = school.ExperimentAreaId
	postStudentAdd.SchoolId = school.Id
	if postStudentAdd.GradeYear < 2000 {
		return false, nil
	}
	if entity.SchoolTypeMapCode[school.SchoolType] == "小" && postStudentAdd.Grade[0:1] != "1" {
		return false, nil
	} else if entity.SchoolTypeMapCode[school.SchoolType] == "初" && postStudentAdd.Grade[0:1] != "2" {
		return false, nil
	} else if entity.SchoolTypeMapCode[school.SchoolType] == "高" && postStudentAdd.Grade[0:1] != "3" {
		return false, nil
	}
	return true, nil
}

type DeleteStudent struct {
	Id []int64 `json:"id"`
}

func (deleteStudent *DeleteStudent) Validate(uid int64, authority byte) (bool, error, string) {
	if len(deleteStudent.Id) == 0 {
		return false, nil, ""
	}
	area := new(entity.Area)
	school := new(entity.School)
	if authority == entity.ManagerAuthority.Area {
		err := area.SelectAllByUserId(uid)
		if err != nil {
			return false, err, ""
		}
	} else if authority == entity.ManagerAuthority.School {
		err := school.SelectAllByUserId(uid)
		if err != nil {
			return false, err, ""
		}
	}
	for i := 0; i < len(deleteStudent.Id); i++ {
		student := new(entity.Student)
		err := student.SelectAllById(deleteStudent.Id[i])
		if err != nil {
			return false, err, ""
		}
		if authority == entity.ManagerAuthority.Area && student.ExperimentAreaId != area.Id {
			return false, nil, ""
		} else if authority == entity.ManagerAuthority.School && student.SchoolId != school.Id {
			return false, nil, ""
		}
		score := new(entity.Score)
		err = score.SelectFirstAllByStudentId(student.Id)
		if err != nil && err != orm.ErrNoRows {
			return false, err, ""
		} else if err == nil {
			return false, err, "无法删除有体质数据记录的学生"
		}
	}
	return true, nil, ""
}

type GetStudentExportAdmin struct {
	ProvinceId   int64
	CityId       int64
	AreaId       int64
	SchoolName   string
	JoinYear     int64
	SchoolRollId string
}

func (getStudentExportAdmin *GetStudentExportAdmin) Validate(provinceId string, cityId string, areaId string, schoolName string, joinYear string, schoolRollId string, c *beego.Controller) bool {
	var err error
	getStudentExportAdmin.ProvinceId, err = c.GetInt64(provinceId)
	if err != nil {
		return false
	}
	getStudentExportAdmin.CityId, err = c.GetInt64(cityId)
	if err != nil {
		return false
	}
	getStudentExportAdmin.AreaId, err = c.GetInt64(areaId)
	if err != nil {
		return false
	}
	getStudentExportAdmin.SchoolName = c.GetString(schoolName)
	getStudentExportAdmin.JoinYear, err = c.GetInt64(joinYear)
	if err != nil {
		return false
	}
	getStudentExportAdmin.SchoolRollId = c.GetString(schoolRollId)
	return true
}

type GetStudentExportArea struct {
	JoinYear     int64
	SchoolId     int64
	SchoolRollId string
}

func (getStudentExportArea *GetStudentExportArea) Validate(joinYear string, schoolId string, schoolRollId string, c *beego.Controller) bool {
	var err error
	getStudentExportArea.JoinYear, err = c.GetInt64(joinYear)
	if err != nil {
		return false
	}
	getStudentExportArea.SchoolId, err = c.GetInt64(schoolId)
	if err != nil {
		return false
	}
	getStudentExportArea.SchoolRollId = c.GetString(schoolRollId)
	return true
}

type GetStudentExportSchool struct {
	SchoolRollId string
}

func (getStudentExportSchool *GetStudentExportSchool) Validate(schoolRollId string, c *beego.Controller) bool {
	getStudentExportSchool.SchoolRollId = c.GetString(schoolRollId)
	return true
}
